/**
 * ComboBox.as
 * Keith Peters
 * version 0.9.4
 * 
 * A button that exposes a list of choices and displays the chosen item. 
 * 
 * Copyright (c) 2010 Keith Peters
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package  com.bases.combo
{
	import com.bases.ImageButton;
	import com.skin.SkinManage;
	
	import flash.display.DisplayObjectContainer;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	public class ComboBox extends Component {
		public static const TOP:String = "top";
		public static const BOTTOM:String = "bottom";
		
		protected var _defaultLabel:String = "";
		//下拉按钮
		private var _dropButton:ImageButton;
    	//protected var _dropDownButton:PushButton;
		protected var _items:Array;
		protected var _labelButton:PushButton;
		protected var _list:List;
		protected var _numVisibleItems:int = 3;
		protected var _open:Boolean = false;
		protected var _openPosition:String = TOP;
		protected var _stage:Stage;
		
		/**
		 * 选择框 
		 * @param parent
		 * @param xpos
		 * @param ypos
		 * @param defaultLabel
		 * @param items
		 */		
		public function ComboBox(parent:DisplayObjectContainer=null, xpos:Number=0, 
								 	ypos:Number=0, defaultLabel:String="", items:Array = null){
			_defaultLabel = defaultLabel;
			_items = items;
			addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
			addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
			super(parent, xpos, ypos);
		}
		
		/**
		 * Initilizes the component.
		 */
		protected override function init():void {
			super.init();
			setSize(100, 22);
			setLabelButtonLabel();
			_dropButton=new ImageButton(SkinManage.getInstance().getClass('DrowDownBmp'),SkinManage.getInstance().getClass('DrowDownBmp'),SkinManage.getInstance().getClass('DrowDownBmp'));
			_dropButton.height=_height;
			this.addChild(_dropButton);
			this._dropButton.addEventListener(MouseEvent.CLICK,onDropDown);
		}
		
		/**
		 * 添加列表
		 */
		protected override function addChildren():void {
			super.addChildren();
			_list = new List(null, 0, 0, _items);
			_list.addEventListener(Event.SELECT, onSelect);
			_labelButton = new PushButton(this, 0, 0, "", onDropDown);
		}
		
		public function setButtonPox(_x:Number,_y:Number):void{
			this._dropButton.x=_labelButton.x+_x;
			this._dropButton.y=_labelButton.y+_y;
		}
		
		/**
		 * 设置项的值
		 */
		protected function setLabelButtonLabel():void {
			if(selectedItem == null) {
				_labelButton.label = _defaultLabel;  //默认值
			} else if(selectedItem is String) {
				_labelButton.label = selectedItem as String;
			} else if(selectedItem.label is String) {
				_labelButton.label = selectedItem.label;
			} else {
				_labelButton.label = selectedItem.toString();
			}
		}
		
		/**
		 * 将列表从舞台移除
		 */
		protected function removeList():void {
			if(_stage.contains(_list)) _stage.removeChild(_list);
			_stage.removeEventListener(MouseEvent.CLICK, onStageClick);
		}

		/////////////////////////////////////
		// public methods 公有方法，操作ComboBox
		/////////////////////////////////////
		public override function draw():void {
			super.draw();
			_labelButton.setSize(_width - _height + 1, _height);
			_labelButton.draw();
			
			_dropButton.x = _width - height;
			
			_list.setSize(_width, _numVisibleItems * _list.listItemHeight);
		}

		public function addItem(item:Object):void {
			_list.addItem(item);
		}
		/**
		 * 按索引添加项
		 * @param item
		 * @param index
		 */
		public function addItemAt(item:Object, index:int):void {
			_list.addItemAt(item, index);
		}
		
		/**
		 * 按项删除
		 * @param item
		 */
		public function removeItem(item:Object):void {
			_list.removeItem(item);
		}
		
		/**
		 * 按索引删除
		 * @param index
		 */
		public function removeItemAt(index:int):void {
			_list.removeItemAt(index);
		}
		
		/**
		 * 移除列表所有内容
		 */
		public function removeAll():void {
			_list.removeAll();
		}
	
		
		///////////////////////////////////
		// event handlers 事件处理
		///////////////////////////////////
		/**
		 * 下拉列表
		 */
		protected function onDropDown(event:MouseEvent):void {
			event.stopImmediatePropagation();
			event.stopPropagation();
			_open = !_open;
			if(_open) {
				var point:Point = new Point();
				if(_openPosition == TOP) {
					point.y = _height;
				} else {
					point.y = -_numVisibleItems * _list.listItemHeight;
				}
				point = this.localToGlobal(point);
				_list.move(point.x, point.y);
				_stage.addChild(_list);
				_stage.addEventListener(MouseEvent.CLICK, onStageClick);
			} else {
				removeList();
			}
		}
		
		/**
		 * 舞台点击或点击按钮
		 * 移除列表
		 */
		protected function onStageClick(event:MouseEvent):void {
			if(event.target == _dropButton || event.target == _labelButton) return;
			if(new Rectangle(_list.x, _list.y, _list.width, _list.height).contains(event.stageX, event.stageY)) return;
			
			_open = false;
			removeList();
		}
		
		/**
		 * 列表选择e.target.selectItem
		 */
		protected function onSelect(event:Event):void {
			_open = false;
			if(stage != null && stage.contains(_list)) {
				stage.removeChild(_list);
			}
			setLabelButtonLabel();
			dispatchEvent(new Event("select"));
		}
		
		/**
		 * 设置舞台
		 */
		protected function onAddedToStage(event:Event):void {
			_stage = stage;
		}
		
		/**
		 * 移除列表
		 */
		protected function onRemovedFromStage(event:Event):void {
			removeList();
		}
		
		
		///////////////////////////////////
		// getter/setters
		///////////////////////////////////
		/**
		 * 选择索引
		 */
		public function set selectedIndex(value:int):void {
			_list.selectedIndex = value;
			setLabelButtonLabel();
		}
		public function get selectedIndex():int {
			return _list.selectedIndex;
		}
		
		/**
		 * 选择项
		 */
		public function set selectedItem(item:Object):void {
			_list.selectedItem = item;
			setLabelButtonLabel();
		}
		public function get selectedItem():Object {
			return _list.selectedItem;
		}
		
		/**
		 * 默认背景
		 */
		public function set defaultColor(value:uint):void {
			_list.defaultColor = value;
		}
		public function get defaultColor():uint {
			return _list.defaultColor;
		}
		
		/**
		 * 选择的背景
		 */
		public function set selectedColor(value:uint):void {
			_list.selectedColor = value;
		}
		public function get selectedColor():uint {
			return _list.selectedColor;
		}
		
		/**
		 * 滑过背景
		 */
		public function set rolloverColor(value:uint):void {
			_list.rolloverColor = value;
		}
		public function get rolloverColor():uint {
			return _list.rolloverColor;
		}
		
		/**
		 * Sets the height of each list item.
		 */
		public function set listItemHeight(value:Number):void {
			_list.listItemHeight = value;
			invalidate();
		}
		public function get listItemHeight():Number {
			return _list.listItemHeight;
		}

		/**
		 * Sets / gets the position the list will open on: top or bottom.
		 */
		public function set openPosition(value:String):void {
			_openPosition = value;
		}
		public function get openPosition():String {
			return _openPosition;
		}

		/**
		 * 默认值
		 */
		public function set defaultLabel(value:String):void {
			_defaultLabel = value;
			setLabelButtonLabel();
		}
		public function get defaultLabel():String {
			return _defaultLabel;
		}

		/**
		 * 设置显示的项数
		 */
		public function set numVisibleItems(value:int):void {
			_numVisibleItems = value;
			invalidate();
		}
		public function get numVisibleItems():int {
			return _numVisibleItems;
		}

		/**
		 * 设置项的数目
		 */
		public function set items(value:Array):void {
			_list.items = value;
		}
		public function get items():Array {
			return _list.items;
		}
		
		/**
		 * Sets / gets the class used to render list items. Must extend ListItem.
		 */
		public function set listItemClass(value:Class):void {
			_list.listItemClass = value;
		}
		public function get listItemClass():Class {
			return _list.listItemClass;
		}
		
		
		/**
		 * Sets / gets the color for alternate rows if alternateRows is set to true.
		 */
		public function set alternateColor(value:uint):void {
			_list.alternateColor = value;
		}
		public function get alternateColor():uint {
			return _list.alternateColor;
		}
		
		/**
		 * Sets / gets whether or not every other row will be colored with the alternate color.
		 */
		public function set alternateRows(value:Boolean):void {
			_list.alternateRows = value;
		}
		public function get alternateRows():Boolean {
			return _list.alternateRows;
		}
	}
}